package com.galaxy.order.consumer;


import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.galaxy.common.core.domain.R;
import com.galaxy.common.mq.config.RabbitConfig;
import com.galaxy.common.mq.config.RabbitTtlQueueConfig;
import com.galaxy.order.api.RemoteCouponService;
import com.galaxy.order.api.RemoteDeviceService;
import com.galaxy.order.domain.CheckStock;
import com.galaxy.order.domain.Order;
import com.galaxy.order.domain.bo.OrderBo;
import com.galaxy.order.domain.bo.OrderDetailBo;
import com.galaxy.order.domain.vo.OrderDetailVo;
import com.galaxy.order.domain.vo.OrderVo;
import com.galaxy.order.service.OrderCouponService;
import com.galaxy.order.service.OrderDetailService;
import com.galaxy.order.service.OrderService;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class OrderTimeoutConsumer {

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderDetailService orderDetailService;

    @Autowired
    private OrderCouponService orderCouponService;

    @Autowired
    private RemoteCouponService service;

    @Autowired
    private RemoteDeviceService deviceService;

    // 消费订单创建的消息
    @RabbitListener(queues = RabbitTtlQueueConfig.ORDER_TIMEOUT_QUEUE)
    @Transactional(rollbackFor = Exception.class)
    public void receive(String message, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
        log.info("receive message: {}", message);
        try {
            OrderBo orderBo = JSON.parseObject(message, OrderBo.class);
            OrderVo orderVo = orderService.queryByOrderNo(orderBo.getOrderNo());
            if((orderVo!=null && orderVo.getStatus() == 2) || (orderVo!=null && orderVo.getStatus() == 5) || (orderVo!=null && orderVo.getStatus() == 4) || (orderVo!=null && orderVo.getStatus() == 3)){
                channel.basicAck(deliveryTag, false);
                return;
            }
            if(orderVo!=null && orderVo.getId()!=null){
                Order order = new Order();
                order.setStatus(4);
                order.setId(orderVo.getId());
                order.setUpdateTime(orderVo.getUpdateTime());
                order.setUpdateBy(orderVo.getUpdateBy());
                order.setCancelTime(LocalDateTime.now());
                order.setCancelReason("超时未付款");
                boolean b = orderService.updateById(order);

                orderCouponService.deleteByOrder(orderVo.getId(), orderVo.getOrderNo());

                R<Boolean> update = service.update(orderVo.getOrderNo());
                List<CheckStock> checkStockList = new ArrayList<>();
                for(OrderDetailVo orderDetailBo : orderVo.getOrderDetail()){
                    CheckStock checkStock = new CheckStock();
                    checkStock.setDeviceId(orderBo.getDeviceId());
                    checkStock.setChannelId(Long.parseLong(orderDetailBo.getChannelNo()));
                    checkStock.setProductId(orderDetailBo.getProductId());
                    checkStock.setStock(orderDetailBo.getQuantity());
                    checkStockList.add(checkStock);
                }

                R<Boolean> updateStock = deviceService.update(checkStockList);
                if (b && update.getData() && updateStock.getData()) {
                    log.info("insert order success");
                    // 手动确认消息，第二个参数为multiple，表示是否批量确认
                    channel.basicAck(deliveryTag, false);
                } else {
                    log.error("insert order fail, message: {}", message);
                    // 拒绝消息，第二个参数为requeue，表示是否重新入队
                    channel.basicReject(deliveryTag, false);
                }
            }else {
                log.error("insert order fail, message: {}", message);
                // 拒绝消息，第二个参数为requeue，表示是否重新入队
                channel.basicReject(deliveryTag, false);
            }



        } catch (Exception e) {
            log.error("处理订单消息失败, message: {}", message, e);
            try {
                // 发生异常时拒绝消息，可以选择是否重新入队
                channel.basicReject(deliveryTag, false);
            } catch (IOException ioException) {
                log.error("拒绝消息失败", ioException);
            }
        }
    }

}
